using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml;
using System.Drawing;
using EfTidyNet;

namespace ImdbRipperBrowser
{
  public class MovieRepository : IMovieRepository
  {
    private string moviesPath;

    public MovieRepository(string moviesPath)
    {
      this.moviesPath = moviesPath;
    }

    public IEnumerable<Movie> FindAll()
    {
      var result = new List<Movie>();
      var movieFiles = Directory.GetFiles(moviesPath, "*.xml", SearchOption.TopDirectoryOnly);
      foreach (var movieFile in movieFiles)
      {
        var movie = new Movie(Path.GetFileName(movieFile));
        result.Add(movie);

        string thumbPath = Path.Combine(Path.GetDirectoryName(movieFile), Path.GetFileNameWithoutExtension(movieFile) + "_thumbnail.jpg");
        if (File.Exists(thumbPath))
        {
          var bmp = new Bitmap(thumbPath);
          movie.Thumbnail = bmp;
        }

        loadMovieValues(movie, movieFile);
      }

      return result.AsEnumerable();
    }

    private static XmlDocument getDocument(string movieFile)
    {
      int iTotalWarn = 0;
      int iTotalErrs = 0;
      string xmlContent = "";
      string error = "";

      using (TidyNet tidy = new TidyNet())
      {
        tidy.Option.InputAsXML(true);
        tidy.TidyFiletoMem(movieFile, ref xmlContent);
        tidy.TotalWarnings(ref iTotalWarn);
        error = tidy.ErrorWarning();
        tidy.TotalErrors(ref iTotalErrs);
      }

      XmlDocument d = new XmlDocument();
      d.LoadXml(xmlContent);
      return d;
    }

    private void loadMovieValuesFromNode(Movie movie, XmlNode node)
    {
      if (node.Name.Equals("url"))
        movie.ImdbUrl = node.InnerText;
      if (node.Name.Equals("date"))
      {
        int y;
        if (int.TryParse(node.InnerText, out y))
          movie.Year = y;
      }
      if (node.Name.Equals("title"))
        movie.Title = node.InnerText;
      if (node.Name.Equals("rating"))
        movie.Rating = getRating(node.InnerText);
      if (node.Name.Equals("genre"))
        addValue(movie.GenresList, node.InnerText);
      if (node.Name.Equals("summary"))
        movie.Summary = node.InnerText;
      if (node.Name.Equals("directors"))
        addValue(movie.DirectorsList, node.InnerText);
      if (node.Name.Equals("writers"))
        addValue(movie.WritersList, node.InnerText);
      if (node.Name.Equals("cast"))
        addValue(movie.CastList, node.InnerText);
    }

    private void loadMovieValues(Movie movie, string movieFile)
    {
      try
      {
        XmlDocument d = getDocument(movieFile);

        for (int i = 0; i < d.FirstChild.ChildNodes.Count; i++)
        {
          var node = d.FirstChild.ChildNodes[i];
          loadMovieValuesFromNode(movie, node);
        }
      }
      catch (Exception ex)
      {
        movie.CastList.Add(ex.Message);
      }
    }

    private static float getRating(string strRating)
    {
      string aux = string.Empty;

      int pos = strRating.IndexOf("/10") - 1;
      while (pos >= 0)
      {
        if (char.IsDigit(strRating[pos]) || (strRating[pos] == '.'))
        {
          aux = strRating[pos] + aux;
          pos--;
        }
        else
        {
          break;
        }
      }

      float result;
      if (float.TryParse(aux, out result))
        return result;
      else
        return 0F;
    }

    private void addValue(IList<string> currentValues, string valueToAdd)
    {
      if (currentValues.Count >= 10)
        return;
      else
        currentValues.Add(valueToAdd);
    }
  }
}
